<template>
  <el-form ref="Form" :model="props.formState" label-width="140px">
    <el-form-item
      v-for="item in formData.filter((v) => !v.hidden)"
      :key="item.dataIndex"
      :name="item.dataIndex"
      :prop="item.dataIndex"
      :label="item.title"
      :rules="item.rules || []"
    >
      <template v-if="item.type == 'input'">
        <el-input
          v-model="formState[item.dataIndex]"
          clearable
          :placeholder="item.placeholder || ' '"
          :disabled="item.disabled"
          v-bind="item.bind"
          autocomplete="off"
          @input="
            ($event) => {
              item.input && item.input($event)
            }
          "
        />
      </template>
      <template v-else-if="item.type == 'select'">
        <el-select
          v-model="formState[item.dataIndex]"
          class="input"
          clearable
          style="width: 100%"
          v-bind="item.bind"
          :disabled="item.disabled"
          :placeholder="item.placeholder || ' '"
          @change="
            ($event) => {
              item.change && item.change($event)
            }
          "
        >
          <el-option
            v-for="option in item.data"
            :key="option.value"
            :label="option.label"
            :value="option.value"
          />
        </el-select>
      </template>
      <template v-else-if="item.type == 'dayTime'">
        <el-date-picker
          v-model="formState[item.dataIndex]"
          clearable
          type="datetime"
          v-bind="item.bind"
          :format="item.format || 'yyyy-MM-dd HH:mm'"
          :value-format="item.format || 'yyyy-MM-dd HH:mm'"
          :disabled="item.disabled"
        />
      </template>
      <template v-else-if="item.type == 'day'">
        <el-date-picker
          v-model="formState[item.dataIndex]"
          clearable
          style="width: 100%"
          type="date"
          v-bind="item.bind"
          :format="item.format || 'yyyy-MM-dd'"
          :value-format="item.format || 'yyyy-MM-dd'"
          :disabled="item.disabled"
        />
      </template>
      <template v-else-if="item.type == 'switch'">
        <el-switch
          v-model="formState[item.dataIndex]"
          :active-value="item.active || item.active === 0 ? item.active : true"
          :inactive-value="item.inactive || item.inactive === 0 ? item.inactive : false"
          :active-text="item.activeText || ''"
          :inactive-text="item.inactiveText || ''"
          v-bind="item.bind"
          :disabled="item.disabled"
          @change="
            ($event) => {
              item.change && item.change($event)
            }
          "
        />
      </template>
      <template v-else-if="item.type == 'radio'">
        <el-radio-group
          v-model="formState[item.dataIndex]"
          v-bind="item.bind"
          :disabled="item.disabled"
          @change="item.change && item.change"
        >
          <el-radio
            v-for="option in item.data"
            :key="option.value"
            :label="option.label"
            :value="option.value"
          />
        </el-radio-group>
      </template>
      <template v-else-if="item.type == 'inputNumber'">
        <el-input-number
          v-model="formState[item.dataIndex]"
          v-bind="item.bind"
          :min="item.min || 0"
          :max="item.max || 99"
          :disabled="item.disabled"
        />
      </template>
      <template v-else-if="item.type == 'multiple'">
        <el-select
          v-model="formState[item.dataIndex]"
          v-bind="item.bind"
          clearable
          multiple
          :disabled="item.disabled"
          :placeholder="item.placeholder || ' '"
        >
          <el-option
            v-for="option in item.data"
            :key="option.value"
            :label="option.label"
            :value="option.value"
          />
        </el-select>
      </template>
      <template v-else-if="item.type == 'cascader'">
        <el-cascader
          v-if="!item.loadData"
          v-model="formState[item.dataIndex]"
          clearable
          :options="item.data"
          :placeholder="item.placeholder || ' '"
          :disabled="item.disabled"
          v-bind="item.bind"
          :props="{
            label: item.label || 'label'
          }"
          style="width: 100%"
          @change="
            ($event) => {
              item.change && item.change($event)
            }
          "
        />
        <el-cascader
          v-else
          v-model="formState[item.dataIndex]"
          clearable
          :options="item.data"
          :props="{
            lazy: true,
            lazyLoad: item.loadData,
            label: item.label || 'label'
          }"
          :placeholder="item.placeholder || ' '"
          :disabled="item.disabled"
          v-bind="item.bind"
          style="width: 100%"
          @change="
            ($event) => {
              item.change && item.change($event)
            }
          "
        />
      </template>
      <template v-else-if="item.type == 'textarea'">
        <el-input
          style="word-break: break-all"
          v-model="formState[item.dataIndex]"
          type="textarea"
          v-bind="item.bind"
          clearable
          :placeholder="item.placeholder || ' '"
          :rows="item.rows || 2"
          :disabled="item.disabled"
          :show-word-limit="true"
        />
      </template>
      <template v-else-if="item.type == 'upload'">
        <el-upload
          :action="action"
          :show-file-list="false"
          :before-upload="beforeUpload"
          @change="handleChange($event, item.dataIndex)"
        >
          <img v-if="formState[item.dataIndex]" :src="formState[item.dataIndex]" />
          <div v-else>
            <i v-if="loading" class="el-icon-loading avatar-uploader-icon" />
            <i v-else class="el-icon-plus avatar-uploader-icon" />
            <div class="ant-upload-text">点击上传</div>
          </div>
        </el-upload>
      </template>
      <template v-else-if="item.type == 'uploadSys'">
        <el-upload
          class="avatar-uploader"
          :action="action"
          :headers="{ 'Platform-Name': 'platform' }"
          list-type="picture"
          :show-file-list="false"
          :on-success="handleAvatarSuccess"
          :before-upload="beforeUpload"
          :on-remove="handleRemove"
        >
          <img class="avatar" v-if="formState[item.dataIndex]" :src="formState[item.dataIndex]" />

          <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
        </el-upload>
        <span
          v-if="formState[item.dataIndex]"
          class="el-upload-list__item-delete"
          @click="handleRemove(file)"
        >
          <el-icon :size="16"><Delete /></el-icon>
        </span>
      </template>
      <template v-else-if="item.type == 'select-tree'">
        <el-popover width="30%" :visible="item.visible" placement="bottom-start" trigger="click">
          <template #reference>
            <el-input
              :value="
                findText(item.data, item.value || 'id', formState[item.dataIndex], item.label) ||
                item.defaultText
              "
              :readonly="true"
              :placeholder="item.placeholder || ' '"
              :disabled="item.disabled"
              @click.native="item.visible = true"
            >
              <template v-if="!item.disabled" #suffix>
                <svg-icon
                  v-if="formState[item.dataIndex] || formState[item.dataIndex] === 0"
                  icon="icon-close-circle"
                  @click.stop="emit('update:formState', { ...formState, [item.dataIndex]: null })"
                />
              </template>
            </el-input>
          </template>
          <div v-click-outside="() => (item.visible = false)" class="popover">
            <el-tree
              :data="item.data"
              :props="{ label: item.label || 'name', children: 'children' }"
              :node-key="item.value || 'id'"
              highlight-current
              :expand-on-click-node="false"
              :current-node-key="formState[item.dataIndex]"
              accordion
              @current-change="
                ($event) => {
                  item.onChange && item.onChange($event)
                  item.visible = false
                }
              "
            />
          </div>
        </el-popover>
      </template>
      <template v-else-if="item.type == 'tree'">
        <form-tree
          :data="item.data"
          v-model="formState[item.dataIndex]"
          :props="{
            label: item.label || 'name',
            children: 'children',
            disabled: () => item.disabled
          }"
          :split="item.split"
          :node-key="item.key || 'id'"
          default-expand-all
          v-bind="item.bind"
          style="width: 100%"
          show-checkbox
        />
      </template>
    </el-form-item>
  </el-form>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import formTree from './form-tree.vue'
import { ElMessage, ClickOutside as vClickOutside } from 'element-plus'
import { Delete, Download, Plus, ZoomIn } from '@element-plus/icons-vue'
import type { UploadProps } from 'element-plus'
const props = defineProps(['formState', 'formData'])
const emit = defineEmits(['update:formState'])

import constant from '@/utils/constant'

const action = ref(constant.uploadUrl)

const beforeUpload = (file) => {
  const isJpgOrPng =
    file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/jpg'
  if (!isJpgOrPng) {
    ElMessage.error('只支持JPG、PNG格式!')
    return Promise.reject()
  }
  const isLt2M = file.size / 1024 / 1024 > 2
  if (isLt2M) {
    ElMessage.error('图片大小不能超过2MB!')
    return Promise.reject()
  }
  return Promise.resolve()
}
const fileList = ref([])
const loading = ref<boolean>(false)
const imageUrl = ref<string>('')
const handleChange = (info, key) => {
  if (info.file.status === 'uploading') {
    loading.value = true
    return
  }
  if (info.file.status === 'done') {
    // Get this url from response in real world.
    const src = info.file.response.data
    // console.log({ ...props.formState, [key]: src })
    emit('update:formState', { ...props.formState, [key]: src })
    loading.value = false
  }
  if (info.file.status === 'error') {
    loading.value = false
    ElMessage.error('upload error')
  }
  return
}

const handleAvatarSuccess: UploadProps['onSuccess'] = (res, file) => {
  if (res.code !== 0) {
    ElMessage.error('上传失败：' + res.message)
    return false
  }

  props.formState['backgroundImage'] = res.data.url
  emit('update:formState', { ...props.formState })
  // dataForm.name = res.data.name
  // dataForm.type = res.data.suffix
  // dataForm.fileUrl = res.data.url
  // dataForm.size = res.data.size
  return true
}

const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
  props.formState['backgroundImage'] = ''
  emit('update:formState', { ...props.formState })
}

const Form: any = ref(null)

const submit = async () => {
  return new Promise((resolve, reject) => {
    Form.value.validate((valid, fields) => {
      if (valid) {
        console.log('submit!')
        resolve()
      } else {
        console.log('error submit!', fields)
        reject(fields)
      }
    })
  })
}

const reset = () => {
  console.log('reset')
  Form.value.resetFields()
}

const findTextLoop = (Data, key, value) => {
  let item
  for (const v of Data) {
    if (v[key] == value) {
      item = v
      break
    } else if (v.children && v.children.length) {
      const i = findTextLoop(v.children, key, value)
      if (i) {
        item = i
        break
      }
    }
  }
  // console.log(item)
  return item
}

const findText = (Data, key, value, label) => {
  // console.log(Data, key, value)
  if (!value) {
    return ''
  }
  if (!Data.length) {
    return ''
  }
  const item = findTextLoop(Data, key, value)
  if (item) {
    return item[label]
  } else {
    return ''
  }
}

defineExpose({
  submit,
  reset
})
</script>

<style lang="scss" scoped>
.avatar-uploader .avatar {
  width: 178px;
  height: 178px;
  display: block;
}
.avatar-uploader {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  text-align: center;
}
:deep(.ant-upload-select-picture-card) {
  height: auto !important;
  .ant-upload {
    min-height: 100px !important;
  }
}
// .avatar-uploader > .ant-upload {
// 	width: 128px;
// 	height: 128px;
// }
.ant-upload-select-picture-card i {
  font-size: 32px;
  color: #999;
}

.ant-upload-select-picture-card .ant-upload-text {
  margin-top: 8px;
  color: #666;
}

.el-upload-list__item-delete {
  display: inline-block;
  z-index: 9999;
  left: 158px;
  top: 5px;
}
</style>
